package org.EasyDevelop.Builder;


import org.EasyDevelop.Bean.Constants;
import org.EasyDevelop.Bean.FieldInfo;
import org.EasyDevelop.Bean.TableInfo;
import org.EasyDevelop.Utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class QueryBuilder {
    private static Logger logger = LoggerFactory.getLogger(QueryBuilder.class);
    public static void execute(TableInfo tableInfo){
        File folder = new File(Constants.PATH_QUERY);

        if(!folder.exists()) folder.mkdirs();
        String queryBeanName = tableInfo.getBeanName() + StringUtils.upperCaseFirstLetter(Constants.SUFFIX_MAP.get("queryParam"));
        File poFile = new File(folder, queryBeanName + Constants.JAVA_SUFFIX);

        OutputStream os = null;
        OutputStreamWriter osw = null;
        BufferedWriter bw = null;

        try {
            os = new FileOutputStream(poFile);
            osw = new OutputStreamWriter(os, "UTF8");
            bw = new BufferedWriter(osw);

            //package
            bw.write("package " + Constants.PACKAGE_QUERY + ";");
            bw.newLine();
            bw.newLine();

            //import
            bw.write("import " + Constants.PACKAGE_QUERY + ".base.BaseParam" + ";");
            bw.newLine();
            //special import

            //date
            if(tableInfo.getHaveDate() || tableInfo.getHaveDateTime()){
                bw.write("import java.util.Date;");
                bw.newLine();
            }
            //bigDecimal
            if(tableInfo.getHaveBigDecimal()){
                bw.write("import java.math.BigDecimal;");
                bw.newLine();
            }
            //serializable and deserializable


            bw.newLine();

            //class comment
            CommentBuilder.createClassComment(bw,tableInfo.getComment());
            //class start
            bw.write("public class " + queryBeanName + " extends BaseParam {");
            bw.newLine();

            List<FieldInfo> queryFieldInfos = new ArrayList<>(tableInfo.getFieldList());

            //填充field字段
            for (FieldInfo fieldInfo : tableInfo.getFieldList()) {
                //field comment
                CommentBuilder.createFieldComment(bw, fieldInfo.getComment());
                //field
                bw.write("\tprivate " + fieldInfo.getJavaType() + " " + StringUtils.processFiled(
                        null == fieldInfo.getFieldName()?"":fieldInfo.getFieldName()
                        ,false) + ";");
                bw.newLine();
                bw.newLine();

                //field like type:String
                if(ArrayUtils.contains(Constants.SQL_STRING_TYPES,fieldInfo.getSqlType())){
                    String queryFieldName = fieldInfo.getPropertyName() + StringUtils.upperCaseFirstLetter(Constants.SUFFIX_MAP.get("queryParamFuzzy"));
                    CommentBuilder.createFieldComment(bw,  fieldInfo.getPropertyName() + "的模糊查询字段");
                    bw.write("\tprivate " + fieldInfo.getJavaType() + " " +
                            queryFieldName
                            + ";");
                    bw.newLine();
                    bw.newLine();
                    FieldInfo info = new FieldInfo();
                    info.setJavaType(fieldInfo.getJavaType());
                    info.setPropertyName(queryFieldName);
                    info.setFieldName(fieldInfo.getFieldName());
                    info.setSqlType(fieldInfo.getSqlType());
                    queryFieldInfos.add(info);
                }

                //date start,end
                if(ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPES,fieldInfo.getSqlType())){
                    if(null != Constants.SUFFIX_MAP.get("timeStart")){
                        String queryFieldName = fieldInfo.getPropertyName() + StringUtils.upperCaseFirstLetter(Constants.SUFFIX_MAP.get("timeStart"));

                        CommentBuilder.createFieldComment(bw,  fieldInfo.getPropertyName() + "的时间段开始");
                        bw.write("\tprivate String" + " " +
                                queryFieldName
                                + ";");
                        bw.newLine();
                        bw.newLine();
                        FieldInfo info = new FieldInfo();
                        info.setJavaType("String");
                        info.setSqlType(fieldInfo.getSqlType());
                        info.setPropertyName(queryFieldName);
                        info.setFieldName(fieldInfo.getFieldName());
                        queryFieldInfos.add(info);
                    }
                    if(null != Constants.SUFFIX_MAP.get("timeEnd")){
                        String queryFieldName = fieldInfo.getPropertyName() + StringUtils.upperCaseFirstLetter(Constants.SUFFIX_MAP.get("timeEnd"));

                        CommentBuilder.createFieldComment(bw,  fieldInfo.getPropertyName() + "的时间段结束");
                        bw.write("\tprivate String " +
                                queryFieldName
                                + ";");
                        bw.newLine();
                        bw.newLine();
                        FieldInfo info = new FieldInfo();
                        info.setSqlType(fieldInfo.getSqlType());
                        info.setJavaType("String");
                        info.setPropertyName(queryFieldName);
                        info.setFieldName(fieldInfo.getFieldName());
                        queryFieldInfos.add(info);
                    }
                }
            }

            //save extend field
            List<FieldInfo> extendFieldLst = new ArrayList<>(queryFieldInfos);
            extendFieldLst.removeAll(tableInfo.getFieldList());
            tableInfo.setExtendFieldLst(extendFieldLst);

            //all construct
            bw.write("\tpublic " + queryBeanName + "(");
            for (int i = 0; i < queryFieldInfos.size(); i++) {
                FieldInfo fieldInfo = queryFieldInfos.get(i);
                bw.write(fieldInfo.getJavaType() + " " + StringUtils.lowerCaseFirstLetter(fieldInfo.getPropertyName()));
                if(i!=queryFieldInfos.size()-1){
                    bw.write(", ");
                }
            }
            bw.write("){");
            bw.newLine();

            for (FieldInfo fieldInfo : queryFieldInfos) {
                bw.write("\t\tthis." + fieldInfo.getPropertyName() + " = " + fieldInfo.getPropertyName() + ";");
                bw.newLine();
            }
            bw.write("\t}");

            bw.newLine();
            bw.newLine();
            //no construct
            bw.write("\tpublic " + queryBeanName + "(");
            bw.write("){");
            bw.newLine();
            bw.write("\t}");

            bw.newLine();
            //method get/set
            for (FieldInfo fieldInfo : queryFieldInfos) {
                String tempField = StringUtils.upperCaseFirstLetter(fieldInfo.getPropertyName());
                //set()
                bw.write("\tpublic void set" + tempField + "(" + fieldInfo.getJavaType() + " " + fieldInfo.getPropertyName() + "){");
                bw.newLine();

                bw.write("\t\tthis." + fieldInfo.getPropertyName() + " = " + fieldInfo.getPropertyName() + ";");
                bw.newLine();

                bw.write("\t}");
                bw.newLine();
                bw.newLine();



                //get()
                bw.write("\tpublic " + fieldInfo.getJavaType() + " get" + tempField + "(){");
                bw.newLine();

                bw.write("\t\treturn this." + fieldInfo.getPropertyName() + ";");
                bw.newLine();

                bw.write("\t}");
                bw.newLine();
                bw.newLine();
            }

            bw.write("}");
            bw.flush();

        } catch (Exception e) {
            logger.error("创建Query文件失败,{}",e);
        } finally {
            if(bw!=null)
                try{
                    bw.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            if(osw!=null)
                try{
                    osw.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            if(os!=null)
                try{
                    os.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
        }

    }


}
